package com.linkai.JUC._04_unsafecollection;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @Description: HashSet（不安全），CopyOnWriteArraySet（安全）
 *               ConcurrentModificationException
 *               LinkedHashSet(有序)：类似于LinkedHashMap和HashMap之间的关系
 *                  LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置，但是它同时使用链表维护元素的次序。
 *                  这样使得元素看起 来像是以插入顺序保存的，
 * @Author: 林凯
 * @Date: 2021/10/24 14:08
 */
public class SetTest {
    public static void main(String[] args) {

        testLinkedSet();

        Set<String> hashSet = new HashSet<>();
        Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<>());
        Set<String> copyOnWriteArraySet = new CopyOnWriteArraySet<>();

        // HashSet 多线程不安全问题
        /*
           解决方案：
           （1） Set<String> set = Collections.synchronizedSet(new HashSet<>());
           CopyOnWriteArraySet 底层就是 CopyOnWriteArrayList
        * */
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                copyOnWriteArraySet.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(copyOnWriteArraySet);
            }, String.valueOf(i)).start();
        }

        while (Thread.activeCount() > 2) {
            // 除了main线程，和gc线程之外，还有线程在执行的话，就一直循环
            // 保证打印最后的长度的时候，其他线程已经执行完毕了。
        }
        System.out.println(copyOnWriteArraySet.size());

    }

    /*
        LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置，但是它同时使用链表维护元素的次序。
        这样使得元素看起 来像是以插入顺序保存的，
    * */
    public static void testLinkedSet() {
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("K1");
        linkedHashSet.add("K2");
        linkedHashSet.add("K3");

        Iterator<String> iterator = linkedHashSet.iterator();
        while (iterator.hasNext()) {
            // 遍历出来的顺序和插入时候的顺序一致
            System.out.println(iterator.next());
        }
    }
}
